﻿using DevExpress.Persistent.BaseImpl;
using DevExpress.Xpo;
using EasyXaf.EntityDesigner.BusinessObjects.Entities;
using EasyXaf.EntityDesigner.BusinessObjects.Enums;
using EasyXaf.EntityDesigner.CodeTemplates;
using System.ComponentModel;
using System.Text;

namespace EasyXaf.EntityDesigner.BusinessObjects;

/// <summary>
/// 领域模型
/// </summary>
public partial class DomainModel : BaseObject
{
    [Browsable(false)]
    public IList<Entity> VisualEntities
    {
        get => EntityDesigns.Select(x => x.Entity).Distinct().ToList();
    }

    [Browsable(false)]
    public IList<Entity> AllEntities
    {
        get
        {
            var entities = new List<Entity>();
            foreach (var referenceModel in ReferenceModels)
            {
                entities.AddRange(referenceModel.AllEntities);
            }
            entities.AddRange(Entities);
            return entities.Distinct().ToList();
        }
    }

    [Browsable(false)]
    public IList<Enumeration> AllEnums
    {
        get
        {
            var enums = new List<Enumeration>();
            foreach (var referenceModel in ReferenceModels)
            {
                enums.AddRange(referenceModel.AllEnums);
            }
            enums.AddRange(Enums);
            return enums.Distinct().ToList();
        }
    }

    private partial IList<DomainModel> GetReferenceModelsDataSource()
    {
        var models = Session.Query<DomainModel>().ToList();
        return models.Where(model => !model.IsReferenceModel(this)).ToList();
    }

    private partial bool GetIsValid()
    {
        return !Session.Query<DomainModel>().Any(x => x.Oid != Oid && x.Name == Name && x.Version == Version);
    }

    public bool IsReferenceModel(DomainModel model)
    {
        if (model == null)
        {
            return false;
        }

        if (model.Oid == Oid)
        {
            return true;
        }

        if (ReferenceModels.Any(x => x.Oid == model.Oid))
        {
            return true;
        }

        return ReferenceModels.Any(x => x.IsReferenceModel(model));
    }

    public void ExportCode(string path, bool generateExtensionEntity)
    {
        foreach (var entity in Entities)
        {
            var entityPath = path;
            var @namespace = entity.GetNamespace();

            if (!string.IsNullOrWhiteSpace(@namespace))
            {
                entityPath = Path.Combine([path, .. @namespace.Split('.')]);
            }

            Directory.CreateDirectory(entityPath);

            File.WriteAllText(Path.Combine(entityPath, $"{entity.Name}.AutoGenerated.cs"), new XpoEntityTemplate(entity).GenerateCode(), Encoding.UTF8);

            if (generateExtensionEntity)
            {
                File.WriteAllText(Path.Combine(entityPath, $"{entity.Name}.cs"), new ExtensionEntityTemplate(entity).GenerateCode(), Encoding.UTF8);
            }
        }

        foreach (var enumeration in Enums)
        {
            var enumPath = path;
            var @namespace = enumeration.GetNamespace();

            if (!string.IsNullOrWhiteSpace(@namespace))
            {
                enumPath = Path.Combine([path, .. @namespace.Split('.')]);
            }

            Directory.CreateDirectory(enumPath);

            File.WriteAllText(Path.Combine(enumPath, $"{enumeration.Name}.cs"), new EnumTemplate(enumeration).GenerateCode(), Encoding.UTF8);
        }
    }
}
